

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/fs.h>

#define DEVNAME "misc_demo"

#define LOGI(fmt, args...) \
	pr_info(DEVNAME "[%04d][@%s]" fmt, __LINE__, __func__, ##args)

#define LOGE(fmt, args...) \
	pr_err(DEVNAME "[%04d][@%s]" fmt, __LINE__, __func__, ##args)

static int misc_demo_open(struct inode *node, struct file *flip)
{

	return 0;
}

static int misc_demo_release(struct inode *node, struct file *flip)
{

	return 0;
}

static ssize_t misc_demo_write(struct file *filep, const char __user *buff, size_t count ,loff_t *fpos)
{
	LOGI("count=%lu, fpos=%llu", count, *fpos);
	*fpos += count;

	return count;
}


static ssize_t misc_demo_read(struct file *filp, char __user *buff, size_t count, loff_t *fpos)
{
	LOGI("count=%lu, fpos=%llu", count, *fpos);
	*fpos += count;
	if(*fpos >  1000000){
		return 0;  // return 0 indicate end of file.
	}	
	return count;
}

static const struct file_operations misc_demo_fops = {
/* .owner = THIS_MODULE, */
	.open = misc_demo_open,
	.release = misc_demo_release,
	.read = misc_demo_read,
	.write = misc_demo_write,
};

static struct miscdevice misc_demo_misc_device = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVNAME,
	.fops = &misc_demo_fops,
};


static int __init misc_demo_init(void)
{
	LOGI("++");
	if (misc_register(&misc_demo_misc_device)) {
		return -1;
	}
	return 0;
}

static void __exit misc_demo_exit(void)
{
	LOGI("++");
	misc_deregister(&misc_demo_misc_device);
}


module_init(misc_demo_init);
module_exit(misc_demo_exit);

MODULE_AUTHOR("tj <tj_wust@163.com>");
MODULE_DESCRIPTION("i2c demo driver");
MODULE_LICENSE("GPL");
